/**
 * 
 */
package com.cqcis.uip.base.framework.utils;

import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;

import com.cqcis.uip.base.framework.UIPTaskException;
import com.cqcis.uip.base.framework.core.Endpoint;
import com.cqcis.uip.base.framework.core.impl.EndpointImpl;

/**
 * 生成Endpoint对象的工具类
 * 
 * @author huangmy
 *
 */
public class EndpointGenerator {	
	/**
	 * 表达式类型
	 */
	public static String ENDPOINT_EXPRESSION_TYPE = Endpoint.TYPE; // 类型
	public static String ENDPOINT_EXPRESSION_DIRECT_SRC = Endpoint.DIRECT_SRC; // 源
	
	// 位置,可以为几个值：1.保留 local(默认.大小写不敏感) 2. 网络地址表达式, 暂时只支持socket
	public static String ENDPOINT_EXPRESSION_LOCATION = Endpoint.LOCATION; 
	public static String ENDPOINT_EXPRESSION_TYPE_DEFAULT_VALUE = Endpoint.TYPE_DEFAULT_VALUE;
	
	private EndpointGenerator() {		
	}
	
	/**
	 * 根据TinPfQueue生成环节实例
	 * @param order
	 * @return
	 */
    public static Endpoint generate(long id, Map<String, String> properties) {
    	Endpoint endpoint = generate(id);
    	
    	if (properties != null) {
    		for (Map.Entry<String, String> entry : properties.entrySet()) {
    			endpoint.setAttribute(entry.getKey(), entry.getValue());
    		}
    	}
    	
    	return endpoint;
    }
    
    /**
     * 从环节编码生成一个环节实例, 属性全部默认为所有
     * @param tacheId
     * @return
     */
    public static Endpoint generate(long id) {
    	Endpoint endpoint = new EndpointImpl(id);
    	
    	/**
    	 * 工单类型
    	 */
    	endpoint.setAttribute(ENDPOINT_EXPRESSION_TYPE, 
    			ENDPOINT_EXPRESSION_TYPE_DEFAULT_VALUE);
    	
    	return endpoint;
    }
    
    /**
     * 从URI表达式生成Endpoint
     * 
     * @param endpointURI
     * @return
     */
    public static Endpoint generateFromURI(String endpointURI) {
    	if (endpointURI == null) {
    		throw new NullPointerException("endpointURI must not be null.");
    	}
    	
    	endpointURI = endpointURI.trim();
    	
    	if (endpointURI.length() == 0) {
    		throw new RuntimeException("endpointURI length must not be zero.");
    	}
    	
    	int idIndex = endpointURI.indexOf("//");
    	if (idIndex <= 0) {
    		return null;
    	}
    	
    	endpointURI = endpointURI.substring(idIndex + 2);
    	if (endpointURI == null) {
    		return null;
    	}
    	
    	int idEndIndex = endpointURI.indexOf("?");
    	
    	Map<String, String> properties = new HashMap<String, String>();
    	long id = 0;
    	String idStr = null;
    	
    	if (idEndIndex > 0) {
    		idStr = endpointURI.substring(0, idEndIndex);  
    		
    		String propsStr = endpointURI.substring(idEndIndex + 1);
        	StringTokenizer stp = new StringTokenizer(propsStr, "&");
        	
    		while(stp.hasMoreTokens()) {
    			String propertyStr = stp.nextToken();
    			propertyStr = propertyStr.trim();
    			if (propertyStr != null && propertyStr.length() > 0) {
    				int index = propertyStr.indexOf('=');
    				String name = propertyStr.substring(0, index);
    				String value = propertyStr.substring(index + 1);
    									
    				properties.put(name, value);
    			}
    		}    		
    	} else {
    		idStr = endpointURI.substring(0);
    	}
    	
    	idStr = StringUtil.trimWhiteToNull(idStr);
    	
    	if (idStr != null) {
    		id = Long.parseLong(idStr);
    	} 
    	
    	return generate(id, properties);
    }
    
    /**
     * 根据环节定义配置字符串, 生成一个环节实例
     * @param endpointExpression
     * @return
     */
    public static Endpoint generate(String endpointExpression) {
    	if (endpointExpression == null) {
    		throw new NullPointerException("tacheDefine must not be null.");
    	}
    	
    	endpointExpression = endpointExpression.trim();
    	
    	if (endpointExpression.length() == 0) {
    		throw new RuntimeException("tacheDefine length must not be zero.");
    	}
    	
    	/*parse properties*/
		int beginIndex = 0;
		int endIndex = 0;
		    	
		beginIndex = endpointExpression.indexOf('(');
		endIndex = endpointExpression.lastIndexOf(')');
		
		//校验格式是否正确
		if (beginIndex == 0 || endIndex == 0) {
			throw new RuntimeException("Tache Formatting Exception. May be '(' ')' invalid.");
		}
		
		if ((beginIndex < 0 && endIndex > 0) 
		   || (beginIndex > 0 && endIndex < 0)
		   || (beginIndex > 0 && (beginIndex == endIndex))) {
			throw new RuntimeException("Tache Formatting Exception. May be '(' ')' invalid.");
		}
		
		String tacheId = null;
		if (beginIndex < 0) {
			tacheId = endpointExpression;
		} else {		
		    tacheId = endpointExpression.substring(0, beginIndex);
		}
		
		Endpoint endpoint = generate(Long.parseLong(tacheId));
		
		String propsStr = null;
		
		if (beginIndex > 0 && endIndex > 0) {
			propsStr = endpointExpression.substring(beginIndex + 1, endIndex);
		}
		
		propsStr = StringUtil.trimWhiteToNull(propsStr);		
		if (propsStr != null) {			
			int begin = -1;
			int end = -1;
			int split = begin + 1;
						
			while ((end = propsStr.indexOf(";", begin + 1)) >= 0) {				
				String t = propsStr.substring(split, end);
				t = StringUtil.trimWhiteToNull(t);
				if (t != null) {
					if (isFinish(t)) {
						setValueOf(endpoint, t);
						split = end + 1;
					}				
				} 
				
				begin = end;
			}
			
			if (split <= 0) {
				setValueOf(endpoint, propsStr);
			} else if (split != propsStr.length()) {
				setValueOf(endpoint, propsStr.substring(split));
			}
		}
				
    	return endpoint;
    }
    
    /**
     * 设置name - value
     * 
     * @param e
     * @param t
     */
    private static void setValueOf(Endpoint e, String t) {
    	int index = t.indexOf('=');
    	if (index < 0) {
    		throw new UIPTaskException("format error: " + t);
    	}
		String name = t.substring(0, index);
		String value = t.substring(index + 1);											
		e.setAttribute(name, value);		
    }
    
    /**
     * 是否完成
     * 
     * @param t
     * @return
     */
    private static boolean isFinish(String t) {
    	char[] ts = t.toCharArray();
    	if (ts == null || ts.length <= 0) {
    		return true;
    	}
    	
    	int left = 0;
    	int right = 0;
    	
    	for (char c : ts) {
    		switch (c) {
    		case '(':
    			left ++;
    			break;
    		case ')':
    			right ++;
    			break;
    		}
    	}
    	
    	if (left == right) {
    		return true;
    	}
    	return false;
    }
}
